//============================================================================
// Name        : basicblock.h
// Changed     : yes
// By	       : bycy
// Version     : 1.0
// Description : 
//============================================================================

#pragma once
#ifndef _BASICBLOCK_H_
#define _BASICBLOCK_H_ 1

#include "dr_api.h"
#include "libdasm.h"
#include <vector>

typedef unsigned int uint;

/*
* instruction_t
*
* add one variable vector<opnd_t> rel_vals
*
* rel_vals represents relevant variables of instruction_t
*/

/* define the structrure for instruction */
struct instruction_t;
struct instruction_t{
	void *instr;
	uint address;
	instruction_t *prev;
	instruction_t *next;
	vector<opnd_t> rel_vals;
};

/* define the structrure for static instruction list*/
struct instruction_list_t;
struct instruction_list_t{
	instruction_t *first;
	instruction_t *last;
};

/* branch kind of a instruction */
typedef enum branch_kind_t{
	SINGLEPATH,		/* has a single branch path */
	TWOPATH,		/* has two branch paths */
	MULTIPATH,		/* has multi branch paths */
	CALLPATH,		/* last instruction is a call */
	RETPATH,		/* last instruction is a ret */
	FALLPATH,		/* has a falling path */
	NODEFINE		/* has not been define */
};

/* Define a struct to store info about a basic block */
struct _basicblock_t;

struct _basicblock_t{
	int id;					/* ID of the basic block when added into CFG */
	uint first_address;		/* the address of first instruction of the BB*/
	uint last_address;		/* the address of last instruction of the BB */
	uint last_length;		/* the length of the last instruction */
	branch_kind_t branch_kind;	/* branch kind of last instr in the BB(no use) */
	_basicblock_t *next_branch;	/* point to next branching BB(no use) */
	_basicblock_t *next_unbranch; /*pointer to next unbranching BB(no use) */
	bool isStatic;			/* whether the basic block is created statically */
	instruction_list_t *bb_instr_list;	
};
typedef struct _basicblock_t basicblock_t;

instruction_t* create_instruction(bool isStatic,uint address);

instruction_list_t* create_instruction_list();

void instruction_list_append(instruction_list_t *list, instruction_t *instr);

/**
 * Create a new basic block
 * @Return the pointer of the new basic block or NULL if fail
 */
basicblock_t* create_basicblock();

/**
 * Create a new basic block
 * @Param:
 * first_addr: beginning address of the basic block
 * last_addr:	last address of the basic block
 * next pointer and branch kind are set outside the function
 * @Return the pointer of the new basic block or NULL if fail
 */
basicblock_t* create_basicblock(uint first_addr,uint last_addr);

/**
 * Delete the basic block
 * @Param:
 * bb: the basic block to be deleted
 */
void delete_basicblock(basicblock_t *bb);

/**
 * Split the original basic block into two part and the original one will be shortened
 * @Param:
 * ori: the original basic block which should not be NULL
 * branch relationship is set outside the function
 * splitAddress: the first BB's last instruction's address 
 * @Return the second basic block after split
 */
basicblock_t* split_basicblock(basicblock_t *ori,uint splitAddress);

#endif